<template>
  <div>
    <el-container class="ov-hidden full-height">
      <PanelHeader
        ref="panelHeader"
        :data="params"
        :online="isOnline"
        :keyboard="inputEvent"
        @event="handleHeaderEvent"
      />

      <!-- 主体信息 -->
      <el-main class="main-box no-padding" style="height: 70%">

        <div
          id="duoJuHeChatPanel"
          class="talks-container lum-scrollbar"
          @scroll="talkPanelScroll($event)"
        >
          <!-- 数据加载状态栏 -->
          <div class="loading-toolbar">
            <span v-if="loadRecord.status == 0" class="color-blue">
              <i class="el-icon-loading" /> 正在加载数据中...
            </span>
            <span
              v-else-if="loadRecord.status == 1"
              class="pointer color-blue"
              @click="loadChatRecords"
            >
              <i class="el-icon-bottom" /> 查看更多消息...
            </span>
            <span v-else> 没有更多消息了... </span>
          </div>

          <!-- 消息主体 -->
          <div v-for="(item, idx) in records" :key="item.recordId">
            <!-- 群消息 -->
            <div v-if="item.msgType == 9" class="message-box">
              <invite-message @cat="catFriendDetail" :invite="item.invite" />
            </div>

            <!-- 撤回消息 -->
            <div v-else-if="item.isRevoke == 1" class="message-box">
              <revoke-message :item="item" />
            </div>

            <div v-else-if="item.msgType == 0" class="message-box">
              <system-text-message :content="item.content" />
            </div>

            <!-- 其它对话消息 -->
            <div
              v-else
              class="message-box record-box"
              :class="{
                'direction-rt': item.float == 'right',
                'checkbox-border': multiSelect.isOpen === true,
              }"
            >
              <aside v-if="item.msgType === 1 || item.msgType === 2 ||item.msgType === 4"  v-show="multiSelect.isOpen" class="checkbox-column">
                <i
                  class="el-icon-success"
                  :class="{ selected: verifyMultiSelect(item.recordId) }"
                  @click="triggerMultiSelect(item.recordId)"
                />
              </aside>
              <aside class="avatar-column">
                <el-avatar
                  class="pointer"
                  :size="30"
                  :src="item.headPortrait"
                  :alt="item.friendRemark?item.friendRemark:item.realName"
                  :title="item.friendRemark?item.friendRemark:item.realName"
                  @click.native="catFriendDetail(item.userId)"
                />
              </aside>
              <main class="main-column">
                <div class="talk-title">
                  <span
                    v-show="
                      item.msgType == 1 ||
                        (item.msgType == 2 && item.float == 'right')
                    "
                    class="time"
                  >
                    <i class="el-icon-time" />
                    {{ parseTime(item.createTime, '{m}月{d}日 {h}:{i}') }}
                  </span>
                </div>

                <div class="talk-content">
                  <span
                    v-show="item.msgType == 2 && item.float == 'left'"
                    class="nickname"
                  >
                    {{ item.realName || item.friendRemark }} |
                    {{ parseTime(item.createTime, '{m}月{d}日 {h}:{i}') }}
                  </span>

                  <!-- 文本消息 -->
                  <text-message
                    v-if="item.msgType == 1"
                    :content="item.content"
                    :float="item.float"
                    :full-width="false"
                    :arrow="true"
                    @contextmenu.native="onCopy(idx, item, $event)"
                  />

                  <!-- 图片消息 -->
                  <image-message
                    v-else-if="item.msgType == 2 && item.file.fileType == 1"
                    :src="item.file.fileUrl"
                    @contextmenu.native="onCopy(idx, item, $event)"
                  />

                  <!-- 音频文件预留 -->
                  <audio-message
                    v-else-if="item.msgType == 2 && item.file.fileType == 2"
                    :src="item.file.fileUrl"
                    @contextmenu.native="onCopy(idx, item, $event)"
                  />

                  <!-- 视频文件预留 -->
                  <video-message
                    v-else-if="item.msgType == 2 && item.file.fileType == 3"
                    :src="item.file.fileUrl"
                    @contextmenu.native="onCopy(idx, item, $event)"
                  />

                  <!-- 文件消息 -->
                  <file-message
                    v-else-if="item.msgType == 2 && item.file.fileType == 4"
                    :file="item.file"
                    :recordId="item.recordId"
                    @contextmenu.native="onCopy(idx, item, $event)"
                  />

                  <!-- 会话记录消息 -->
                  <forward-message
                    v-else-if="item.msgType == 3"
                    :forward="item.forward"
                    :recordId="item.recordId"
                    @contextmenu.native="onCopy(idx, item, $event)"
                  />

                  <!-- 代码块消息 -->
                  <code-message
                    v-else-if="item.msgType == 4"
                    :code="item.codeBlock.codeContent"
                    :lang="item.codeBlock.codeLang"
                    :maxwidth="true"
                    @contextmenu.native="onCopy(idx, item, $event)"
                  />

                  <!-- 投票消息 -->
                  <vote-message
                    v-else-if="item.msgType == 5"
                    :recordId="item.recordId"
                    :vote="item.vote"
                  />

                  <!-- 登录消息 -->
                  <login-message
                    v-else-if="item.msgType == 8"
                    :detail="item.login"
                  />

                  <!-- 未知消息 -->
                  <div class="unknown-msg" v-else>
                    未知消息类型[{{ item.msgType }}]
                  </div>

                  <!-- 消息引用(预留) -->
                  <!-- <reply-message /> -->
                </div>
              </main>
            </div>

            <!-- 消息时间 -->
            <div
              v-show="compareTime(idx, item.createTime)"
              class="datetime no-select"
              v-text="sendTime(item.createTime)"
            />
          </div>
        </div>

        <!-- 置底按钮 -->
        <transition name="el-fade-in-linear">
          <div
            v-show="tipsBoard"
            class="tips-board pointer"
            @click="talkPanelScrollBottom"
          >
            <i class="el-icon-arrow-down"/>
            <span>回到底部</span>
          </div>
        </transition>

        <!-- 新消息气泡 -->
        <div
          v-show="tipsBoard && unreadMessage.num"
          class="talk-bubble pointer no-select"
          @click="talkPanelScrollBottom"
        >
          <i class="el-icon-chat-dot-round" />
          <span>新消息({{ unreadMessage.num }}条)</span>
          <span>
            &nbsp;#{{ unreadMessage.realName }}#
            {{ unreadMessage.content }}
          </span>
        </div>
      </el-main>


      <!-- 页脚信息 -->
      <el-footer class="footer-box" style="height: 30%">
        <template v-if="multiSelect.isOpen === false">
          <MeEditor
            @send="submitSendMessage"
            @keyboard-event="onKeyboardEvent"
          />
        </template>
        <template v-else>
          <PanelToolbar
            v-model="multiSelect.items.length"
            @event="handleMultiMode"
          />
        </template>
      </el-footer>

      <!-- 群设置侧边栏 -->
      <div
        class="sidebar-box"
        :class="{ show: group.panel }"
        v-show="group.panel"
        v-outside="hideChatGroup"
      >
        <GroupPanel
          v-if="params.talkType == 2"
          :groupId="params.receiverId"
          @close="hideChatGroup"
          @send-group="hideChatGroup"
          @quit-group="quitGroupSuccess"
          @disturb-change="disturbChange"
          @group-info="syncGroupInfo"
        />
      </div>
    </el-container>

    <!-- 消息管理器 -->
    <transition name="el-fade-in-linear">
      <TalkSearchRecord
        v-if="findChatRecord"
        :params="{
          talkType: params.talkType,
          receiverId: params.receiverId,
          title: params.realName,
        }"
        @close="findChatRecord = false"
      />
    </transition>

    <!-- 群公告组件 -->
    <transition name="el-fade-in-linear">
      <GroupNotice
        v-if="group.notice"
        :groupId="params.receiverId"
        @close="group.notice = false"
      />
    </transition>
  </div>
</template>
<script>
import { mapState } from 'vuex'
import TalkSearchRecord from '@/components/DuoJuHe/Chat/chat/TalkSearchRecord'
import GroupPanel from '@/components/DuoJuHe/Chat/group/GroupPanel'
import GroupNotice from '@/components/DuoJuHe/Chat/group/GroupNotice'
import MeEditor from '@/components/DuoJuHe/Chat/editor/MeEditor'
import PanelHeader from './PanelHeader'
import PanelToolbar from './PanelToolbar'
import SocketInstance from '@/utils/socket-instance'
import { formateTime, parseTime, copyTextToClipboard } from '@/utils/functions'
import {
  queryChatTalkRecordPageResList,
  forwardTalkRecord,
  batchDeleteRecordByRecordIdList,
  revokeRecordByRecordId,
  deleteRecordByRecordId
} from '@/api/chat/im/chatTalkRecord'


export default {
  name: 'TalkEditorPanel',
  components: {
    MeEditor,
    GroupPanel,
    TalkSearchRecord,
    GroupNotice,
    PanelToolbar,
    PanelHeader,
  },
  props: {
    // 对话相关参数
    params: {
      type: Object,
      default: function() {
        return {
          // 消息来源（1：好友私信 2:群聊）
          talkType: 0,
          // 消息接收者ID（好友ID或者群聊ID）
          receiverId: 0,
          //名称
          realName: '',
        }
      },
    },

    // 用户是否在线
    isOnline: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      // 记录加载相关参数
      loadRecord: {
        status: 0,
        minRecord: 0,
      },

      //每次加载数量
      loadRows:10,
      //分页数
      loadPage:1,
      //总数量
      loadTotal:0,
      // 多选相关操作
      multiSelect: {
        isOpen: false,
        items: [],
        mode: 0,
      },

      // 群组Box
      group: {
        panel: false,
        notice: false,
      },

      // 键盘输入事件
      keyboardEvent: {
        isShow: false,
        time: 0,
      },

      // 聊天记录管理器数据
      findChatRecord: false,

      // 置底按钮是否显示
      tipsBoard: false,
    }
  },
  computed: {
    ...mapState({
      unreadMessage: state => state.talks.unreadMessage,
      inputEvent: state => state.notify.inputEvent,
      uid: state => state.permission.userId,
      records: state => state.dialogue.records,
      indexName: state => state.dialogue.indexName,
    }),
  },
  watch: {
    // 监听面板传递参数
    params() {
      this.loadRecord.minRecord = 0
      this.loadTotal = 0
      this.loadPage = 1
      this.tipsBoard = false
      this.multiSelect = {
        isOpen: false,
        items: [],
        mode: 0,
      }
      this.loadChatRecords()
    },
  },
  mounted() {
    this.loadChatRecords()
  },
  methods: {
    parseTime,
    sendTime: formateTime,

    // 处理 Header 组件事件
    handleHeaderEvent(event_name) {
      switch (event_name) {
        case 'history':
          this.findChatRecord = true
          break
        case 'notice':
          this.group.notice = true
          break
        case 'setting':
          this.group.panel = true
          break
      }
    },

    // 回车键发送消息回调事件
    submitSendMessage(content) {
      SocketInstance.emit('event_talk', {
        senderId: this.uid,
        receiverId: this.params.receiverId,
        talkType: this.params.talkType,
        textMessage: content,
      })

      this.$store.commit('UPDATE_TALK_ITEM', {
        indexName: this.indexName,
        draftText: '',
      })
    },

    // 推送编辑事件消息
    onKeyboardEvent(text) {
      this.$store.commit('UPDATE_TALK_ITEM', {
        indexName: this.indexName,
        draftText: text,
      })

      // 判断当前对话是否属于私聊信息
      if (this.params.talkType == 2 || !this.isOnline) return

      // 判断是否推送键盘输入事件消息
      if (!this.$store.state.settings.keyboardEventNotify) {
        return false
      }

      let time = new Date().getTime()
      // 判断在两秒内是否已推送事件
      if (this.keyboardEvent.time != 0 && time - this.keyboardEvent.time < 2000)
        return

      this.keyboardEvent.time = time

      // 调用父类Websocket组件发送消息
      SocketInstance.emit('event_keyboard', {
        senderId: this.uid,
        receiverId: this.params.receiverId,
      })
    },

    // 加载用户聊天详情信息
    loadChatRecords() {
      const userId = this.uid
      let lastRecordId = this.loadRecord.minRecord
      const data = {
        lastRecordId: lastRecordId===0?"":lastRecordId,
        receiverId: this.params.receiverId,
        talkType: this.params.talkType,
        rows: this.loadRows,
        page: this.loadPage,
      }

      this.loadRecord.status = 0
      let el = document.getElementById('duoJuHeChatPanel')
      let scrollHeight = el.scrollHeight
      queryChatTalkRecordPageResList(data)
        .then(res => {
          // 防止点击切换过快消息返回延迟，导致信息错误
          if ((data.receiverId != this.params.receiverId &&
              data.talkType != this.params.talkType)
          ) {
            return
          }

          const records = res.data.records.map(item => {
            item.float = 'center'
            if (item.userId) {
              item.float = item.userId == userId ? 'right' : 'left'
            }
            this.loadRecord.minRecord = item.recordId
            return item
          })

          // 判断是否是初次加载
          if (data.lastRecordId == 0) {
            this.loadPage = 1
            this.$store.commit('SET_DIALOGUE', [])
          }

          this.$store.commit('UNSHIFT_DIALOGUE', records.reverse())

          //this.loadRecord.status = records.length >= this.loadRows ? 1 : 2
          this.loadTotal = records.length+this.loadTotal
          this.loadRecord.status = res.data.total >this.loadTotal ? 1 : 2
          if (this.loadRecord.status===1){
            this.loadPage++;
          }
          //this.loadRecord.minRecord = res.data.recordId

          this.$nextTick(() => {
            if (data.lastRecordId == 0) {
              el.scrollTop = el.scrollHeight
            } else {
              el.scrollTop = el.scrollHeight - scrollHeight
            }
          })
        })
        .catch(() => {
          this.loadRecord.status = 1
        })
    },

    // 多选处理方式
    handleMultiMode(value) {
      if (value == 'close') {
        this.closeMultiSelect()
        return false
      }

      if (this.multiSelect.items.length <= 1) {
        this.$modal.msgError("至少选择两条记录!")
        return false
      }

      if (this.multiSelect.items.length >10) {
        this.$modal.msgError("一次最多只能转发10条记录!")
        return false
      }

      if (value == 'forward' || value == 'merge_forward') {
        this.multiSelect.mode = value == 'forward' ? 1 : 2
        if (this.verifyMultiSelectType(3)) {
          this.$notify({
            title: '消息转发',
            message: '会话记录不支持合并转发',
          })
          return false
        }

        this.$contacts({
          confirm: this.confirmSelectContacts,
        })
      } else if (value == 'delete') {
        this.multiSelect.mode = 3
        // 批量删除
        let ids = this.multiSelect.items
        batchDeleteRecordByRecordIdList({
          talkType: this.params.talkType,
          receiverId: this.params.receiverId,
          recordIdList: ids,
        }).then(res => {
          this.delRecords(ids).closeMultiSelect()
        })
      }
    },

    // 确认消息转发联系人事件
    confirmSelectContacts(data) {
      let user_ids = []
      let group_ids = []
      data.forEach(item => {
        if (item.talkType == 1) {
          user_ids.push(item.receiverId)
        } else {
          group_ids.push(item.receiverId)
        }
      })
      if (user_ids.length===0&&group_ids.length===0){
        this.$modal.msgError("请选择转发联系人!")
        return false
      }

      forwardTalkRecord({
        forwardMode: this.multiSelect.mode,
        talkType: this.params.talkType,
        receiverId: this.params.receiverId,
        recordIdList: this.multiSelect.items,
        receiveUserIdList: user_ids,
        receiveGroupIdList: group_ids,
      }).then(res => {
        if (res&&res.errorCode === 0) {
          this.closeMultiSelect()
          this.$notify({
            title: '消息转发',
            message: '消息转发成功...',
            type: 'success',
          })
        }
      })
    },

    // 处理消息时间是否显示
    compareTime(index, datetime) {
      if (datetime == undefined) {
        return false
      }

      if (this.records[index].isRevoke == 1) {
        return false
      }

      datetime = datetime.replace(/-/g, '/')
      let time = Math.floor(Date.parse(datetime) / 1000)
      let currTime = Math.floor(new Date().getTime() / 1000)

      // 当前时间5分钟内时间不显示
      if (currTime - time < 300) return false

      // 判断是否是最后一条消息,最后一条消息默认显示时间
      if (index == this.records.length - 1) {
        return true
      }

      let nextDate = this.records[index + 1].createTime.replace(/-/g, '/')

      return !(
        parseTime(new Date(datetime), '{y}-{m}-{d} {h}:{i}') ==
        parseTime(new Date(nextDate), '{y}-{m}-{d} {h}:{i}')
      )
    },

    // 查看好友用户信息
    catFriendDetail(value) {
      this.$user(value)
    },

    // 撤回消息
    revokeRecords(index, item) {
      revokeRecordByRecordId({
        recordId: item.recordId,
      }).then(res => {
        this.$store.commit('UPDATE_DIALOGUE', { recordId: item.recordId, isRevoke: 1 })
      })
    },

    // 删除消息
    removeRecords(index, item) {
      let receiverId = item.receiverId
      if (item.talkType == 1 && item.userId != this.uid) {
        receiverId = item.userId
      }
      deleteRecordByRecordId({
        talkType: item.talkType,
        receiverId: receiverId,
        recordId: item.recordId,
      }).then(res => {
        this.$store.commit('DELETE_DIALOGUE', index)
      })
    },

    // 单条转发消息
    forwardRecords(idx, item) {
      this.multiSelect.mode = 1
      this.multiSelect.items.push(item.recordId)
      this.$contacts({
        confirm: this.confirmSelectContacts,
      })
    },

    // 从列表中删除记录
    delRecords(arr) {
      this.$store.commit('BATCH_DELETE_DIALOGUE', arr)
      return this
    },

    // 开启多选模式
    openMultiSelect() {
      this.multiSelect.isOpen = true
    },

    // 关闭多选模式
    closeMultiSelect() {
      this.multiSelect.isOpen = false
      this.multiSelect.items = []
    },

    // 判断记录是否选中
    verifyMultiSelect(recordsId) {
      return this.multiSelect.items.indexOf(recordsId) >= 0
    },

    // 触发多选事件
    triggerMultiSelect(recordsId) {
      let i = this.multiSelect.items.indexOf(recordsId)
      if (i >= 0) {
        this.multiSelect.items.splice(i, 1)
      } else {
        if (this.multiSelect.items.length > 10) {
          this.$notify({
            title: '温馨提示',
            message: '批量操作最大支持10条数据...',
          })
          return false
        }
        this.multiSelect.items.push(recordsId)
      }
    },

    // 验证是否存在选择的指定类型的消息
    verifyMultiSelectType(type) {
      return this.records.some(item => {
        return this.verifyMultiSelect(item.recordId) && item.msgType == type
      })
    },

    // 消息点击右键触发自定义菜单
    onCopy(idx, item, event) {
      let menus = []
      let content = ''
      if (document.getElementById('copy_class_' + item.recordId)) {
        content = document.getElementById('copy_class_' + item.recordId).innerText
      }

      if (content) {
        menus.push({
          label: '复制',
          icon: 'el-icon-document-copy',
          customClass: 'cus-contextmenu-item',
          onClick: () => {
            copyTextToClipboard(content)
          },
        })
      }

      if (item.userId == this.uid) {
        let time =
          new Date().getTime() - Date.parse(item.createTime.replace(/-/g, '/'))
        if (Math.floor(time / 1000 / 60) < 2) {
          menus.push({
            label: '撤回',
            icon: 'el-icon-s-flag',
            customClass: 'cus-contextmenu-item',
            onClick: () => {
              this.revokeRecords(idx, item)
            },
          })
        }
      }

      menus.push({
        label: '删除',
        icon: 'el-icon-delete',
        customClass: 'cus-contextmenu-item',
        onClick: () => {
          this.removeRecords(idx, item)
        },
      })

      let msgType = item.msgType;
      if (msgType===1 || msgType===2 || msgType===4) {
        menus.push({
          label: '转发',
          icon: 'el-icon-s-promotion',
          customClass: 'cus-contextmenu-item',
          onClick: () => {
            this.forwardRecords(idx, item)
          },
        })


        menus.push({
          label: '多选',
          icon: 'el-icon-finished',
          customClass: 'cus-contextmenu-item',
          onClick: () => {
            this.openMultiSelect()
          },
        })
      }

  /*    menus.push({
        label: '引用',
        icon: 'el-icon-connection',
        customClass: 'cus-contextmenu-item',
        onClick: () => {
          this.$modal.msgError("功能开发中!")
        },
      })*/


      // 判断是否是图片消息
      if (item.msgType == 2 && item.file.fileType == 1) {
        menus.push({
          label: '收藏',
          icon: 'el-icon-picture',
          customClass: 'cus-contextmenu-item',
          onClick: () => {
            this.$store.commit('SAVE_USER_EMOTICON', {
              recordId: item.recordId,
            })
          },
        })
      }

      this.$contextmenu({
        items: menus,
        event,
        customClass: 'cus-contextmenu',
        zIndex: 3,
        minWidth: 120,
      })

      this.closeMultiSelect()
      event.preventDefault()
    },

    hideChatGroup() {
      this.group.panel = false
    },

    // 修改群聊免打扰状态
    disturbChange(detail) {
      this.$store.commit('UPDATE_TALK_ITEM', {
        indexName: `2_${this.params.receiverId}`,
        isDisturb: parseInt(detail.status),
      })
    },

    // 退出群聊回调事件
    quitGroupSuccess() {
      this.$emit('close-talk')
    },

    // 同步群信息
    syncGroupInfo(groupInfo) {
      this.$refs.panelHeader.setGroupNum(groupInfo.membersNum)
    },

    // 对话面板滚动事件
    talkPanelScroll(e) {
      if (e.target.scrollTop == 0 && this.loadRecord.status == 1) {
        this.loadChatRecords()
        return
      }

      const height = e.target.scrollTop + e.target.clientHeight + 5
      this.tipsBoard = height < e.target.scrollHeight
      if (this.tipsBoard == false && this.unreadMessage.num > 0) {
        this.$store.commit('CLEAR_TALK_UNREAD_MESSAGE')
      }
    },

    // 聊天版本滚动到底部
    talkPanelScrollBottom() {
      let el = document.getElementById('duoJuHeChatPanel')
      el.scrollTop = el.scrollHeight
    },
  },
}
</script>
<style lang="less" scoped>
.main-box {
  position: relative;
}

/* 面板页脚 */
.footer-box {
  height: 160px !important;
  padding: 0;
  border-top: 1px solid #f5f5f5;
}

/* 侧边栏css */
.sidebar-box {
  position: absolute;
  width: 350px;
  height: 100%;
  top: 0px;
  right: -350px;
  z-index: 1;
  background: white;
  transition: all 0.5s ease-in-out;
  -moz-transition: all 0.5s ease-in-out;
  -webkit-transition: all 0.5s ease-in-out;
  -o-transition: all 0.5s ease-in-out;

  &.show {
    right: 0;
    box-shadow: 0 0 14px #e2e1e1;
  }
}

.tips-board {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  left: 0;
  right: 0;
  margin: 0 auto;
  bottom: 20px;
  height: 30px;
  width: 100px;
  border-radius: 20px;
  font-size: 12px;
  background-color: #fff;
  box-shadow: 0 2.5px 10px 0 rgba(31, 35, 41, 0.1);
  color: #1f2329;

  span {
    margin-left: 5px;
    margin-top: -2px;
  }

  .svg {
    width: 10px;
    height: 10px;
    color: black;
  }
}

.talk-bubble {
  position: absolute;
  left: 0px;
  bottom: 20px;
  max-width: 300px;
  height: 40px;
  line-height: 40px;
  border-radius: 0 20px 20px 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: white;
  padding: 0 15px 0 30px;
  font-size: 13px;
  background: #409eff;

  i {
    font-size: 22px;
    position: absolute;
    left: 5px;
    top: 9px;
  }
}

.talks-container {
  height: 100%;
  width: 100%;
  box-sizing: border-box;
  padding: 10px 15px 30px;
  overflow-y: auto;

  .message-box {
    width: 100%;
    min-height: 30px;
    margin-bottom: 5px;
  }

  .loading-toolbar {
    height: 30px;
    line-height: 30px;
    margin: 5px 0;
    text-align: center;
    user-select: none;
    font-size: 13px;
    color: #cec4c4;

    .color-blue {
      color: #409eff;
    }
  }

  .datetime {
    height: 30px;
    line-height: 30px;
    color: #ccc9c9;
    font-size: 12px;
    text-align: center;
    margin: 5px 0;
  }

  .record-box {
    display: flex;
    flex-direction: row;
    transition: 0.5s ease;

    .checkbox-column {
      display: flex;
      justify-content: center;
      flex-basis: 40px;
      flex-shrink: 0;
      order: 1;
      user-select: none;
      padding-top: 25px;

      i {
        color: #ccc;
        cursor: pointer;
        font-size: 22px;
        &.selected {
          color: #409eff !important;
        }
      }
    }

    .avatar-column {
      width: 40px;
      flex-basis: 40px;
      flex-shrink: 0;
      display: flex;
      align-items: center;
      order: 2;
      user-select: none;
      padding-top: 22px;
      flex-direction: column;
    }

    .main-column {
      flex: 1 auto;
      order: 3;
      position: relative;
      box-sizing: border-box;
      padding: 5px;
      overflow: hidden;

      .talk-title {
        display: flex;
        align-items: center;
        height: 15px;
        margin-bottom: 2px;
        font-size: 10px;
        user-select: none;
        color: #a7a0a0;
        opacity: 0;
        transition: 0.5s ease;

        &.show {
          opacity: 1 !important;
        }

        span {
          transform: scale(0.9);
        }
      }

      .talk-content {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        box-sizing: border-box;
        width: 100%;

        .nickname {
          font-size: 12px;
          color: #a7a0a0;
          margin: -4px 0 4px -8px;
          transform: scale(0.9);
        }
      }

      &:hover {
        .talk-title {
          opacity: 1;
        }
      }
    }

    &.direction-rt {
      .avatar-column {
        order: 3;
      }

      .main-column {
        order: 2;

        .talk-title {
          justify-content: flex-end;
        }

        .talk-content {
          align-items: flex-end;
        }
      }
    }

    &.checkbox-border {
      border: 1px dashed #c4c4ec;
      &:hover {
        border-color: #409eff;
      }
    }
  }
}
</style>
